/*
 * Copyright (C) 2010 Interactive Media Management
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package dk.i2m.converge.core.search;

import eu.medsea.util.MimeUtil;
import java.io.File;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.common.SolrInputDocument;

/**
 * Singleton factory for indexing {@link File}s based on their characteristics.
 *
 * @author Allan Lykke Christensen
 */
public class IndexingFactory {

    private static final Logger logger = Logger.getLogger(IndexingFactory.class.getName());

    /** Mime type to use if it could not be detected. */
    private static final String UNKNOWN_MIME_TYPE = "application/x-unknown-mime-type";

    /** Singleton instance. */
    private static IndexingFactory instance = null;

    /** Map of supported indexers by mime type. */
    private Map<String, Indexer> supportedMimeTypes = new HashMap<String, Indexer>();

    private Map<String, SolrServer> searchEngines = new HashMap<String, SolrServer>();

    /**
     * Private constructor used by the {@link IndexingFactory#getInstance()}.
     */
    private IndexingFactory() {
//        JpegIndexer jpegIndexer = new JpegIndexer();
//        supportedMimeTypes.put("image/jpeg", jpegIndexer);
//        supportedMimeTypes.put("image/pjpeg", jpegIndexer);
    }

    /**
     * Gets an instance of the {@link IndexingFactory}.
     *
     * @return Instance of the {@link IndexingFactory}
     */
    public static IndexingFactory getInstance() {
        if (instance == null) {
            instance = new IndexingFactory();
        }

        return instance;
    }

    /**
     * Gets an instance of an Apache Solr server registered with the
     * {@link IndexingFactory}. Once a server has been requested it is cached
     * for later retrieval. A server is cached for each unique URL.
     *
     * @param url
     *          URL of the Apache Solr server
     * @return
     * @throws MalformedURLException
     */
    public SolrServer getSolrServer(String url) throws MalformedURLException {

        if (!searchEngines.containsKey(url)) {
            logger.log(Level.INFO, "Creating new Apache Solr client for {0}", new Object[]{url});
            CommonsHttpSolrServer solrServer = new CommonsHttpSolrServer(url);
            solrServer.setSoTimeout(5000);  // socket read timeout
            solrServer.setConnectionTimeout(10000);
            solrServer.setDefaultMaxConnectionsPerHost(100);
            solrServer.setMaxTotalConnections(100);
            solrServer.setFollowRedirects(false);  // defaults to false
            solrServer.setAllowCompression(true);
            solrServer.setMaxRetries(1); // defaults to 0.  > 1 not recommended.
            searchEngines.put(url, solrServer);
        } else {
            logger.log(Level.INFO, "Reusing existing Apache Solr client for {0}", new Object[]{url});
        }

        return searchEngines.get(url);
    }

    /**
     * Indexes a {@link File}.
     *
     * @param file
     *          {@link File} to index
     * @return {@link Document} representing the index of the {@link File}
     */
    public SolrInputDocument index(File file) throws CannotIndexException {

        // Detect MIME type of file
        String mimeType = MimeUtil.getMimeType(file);

        if (mimeType == null) {
            mimeType = UNKNOWN_MIME_TYPE;
        }

        // Obtain indexer for MIME type
        if (mimeType.indexOf(",") != -1) {
            String[] mimeTypes = mimeType.split(",");
            mimeType = mimeTypes[0];
        }

        if (supportedMimeTypes.containsKey(mimeType)) {
            Indexer indexer = supportedMimeTypes.get(mimeType);
            return indexer.index(file, mimeType);
        } else {
            throw new CannotIndexException("Mime-type [" + mimeType + "] not supported");
        }
    }
}
